/* $Id: memory.h 17 2007-01-02 17:31:52Z judas $ */

#ifndef NIH_MEMORY_H
#define NIH_MEMORY_H 1

#include <nih/cdefs.h>

BEGIN_C_DECLS

#if HAVE_STDBOOL_H
#include <stdbool.h>
#endif /* HAVE_STDBOOL_H */
#include <stdlib.h>
#include <sys/types.h>

/* System memory statistics */

extern ssize_t nih_memtotal(bool inc_swap);

extern ssize_t nih_memavail(bool inc_swap);

/* Process memory statistics */

extern ssize_t nih_memused(bool inc_swap);

extern ssize_t nih_memalloced();

/* Memory dump, e.g. for logging */

struct nih_dump_cfg {
        size_t adwidth;
        char *adsep;
        size_t cols;
        size_t group;
        char *grsep;
        char *prisep;
        char nonpri;
        bool upper;
};

extern ssize_t nih_memdump_own(struct nih_dump_cfg *cfg, char **buf,
                               const void *ptr, size_t dump_len);

extern inline ssize_t nih_memdump(char **buf, const void *ptr, size_t dump_len)
{
        return nih_memdump_own(NULL, buf, ptr, dump_len);
}

/* Out of memory handling */

enum nih_oom_failure {
        NIH_MALLOC,
        NIH_CALLOC,
        NIH_REALLOC
};

typedef void nih_oom_fatal_fnc(enum nih_oom_failure failure,
                               const void *ptr, size_t size);

extern nih_oom_fatal_fnc *nih_oom_fatal;

extern inline void *nih_malloc(size_t size)
{
        void *res;

        res = malloc(size);
        if (!res) {
                if (nih_oom_fatal)
                        nih_oom_fatal(NIH_MALLOC, NULL, size);
                else
                        abort();
        }

        return res;
}

extern inline void *nih_calloc(size_t nmemb, size_t size)
{
        void *res;

        res = calloc(nmemb, size);
        if (!res) {
                if (nih_oom_fatal)
                        nih_oom_fatal(NIH_CALLOC, NULL, nmemb * size);
                else
                        abort();
        }

        return res;
}

extern inline void *nih_realloc(void *ptr, size_t size)
{
        void *res;

        res = realloc(ptr, size);
        if (!res) {
                if (nih_oom_fatal)
                        nih_oom_fatal(NIH_REALLOC, ptr, size);
                else
                        abort();
        }

        return res;
}

extern inline void nih_free(void *ptr)
{
        free(ptr);
}

END_C_DECLS

#endif /* NIH_MEMORY_H */

